<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <button @click="increment">count: {{ count }}</button>
    <button @click="incrementObj">countValObj.countVal.count: {{ countValObj.countVal.count }}</button>
  </div>
  <script type="module">
    import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
    createApp({
      data() {
        return {
          count: 0,
          countValObj: {
            countVal: {
              count: 0
            }
          },
          someObject: {}
        }
      },
      mounted() {
        // 第一种方式，可以使用组件实例的 `$watch()` 函数来命令式的创建一个监听器
        // 函数的返回值是一个可以取消监听的函数
        const unwatchFunc = this.$watch('count', (newVal, oldVal) => {
          console.log('watch count: ', newVal, oldVal)
          // 取消监听
          unwatchFunc()
        })
      },
      watch: {
        // 第二种方式，这里的监听器或者使用 `$watch()` 指定的监听，默认情况下，在组件卸载时会自动停止监听
        count(newVal, oldVal) {
          console.log('watch count: ', newVal, oldVal)
        },
        'countValObj.countVal.count': {
          handler(newVal, oldVal) {
            console.log('watch countVal.countObj.count: ', newVal, oldVal)
          }
        },
        someObject: {
          handler(newVal, oldVal) {
            // 监听器的回调函数
          },
          // 深层监听
          // 深度监听需要遍历被监听对象所有嵌套的属性，所以非常耗费性能
          deep: true,
          // 立即回调函数
          // `watch` 默认是懒监听的，有时候需要在创建监听器时强制立即执行回调函数
          immediate: true,
          // 刷新时机,
          // 当更改了响应式状态时，可能同时触发 Vue 组件更新和监听器回调
          // 默认情况下，用户创建的监听器回调是在 Vue 组件更新之前执行的，也就是说在监听器中获取到的 DOM 是更新之前的，
          // 如果想在监听器中能访问被 Vue 更新之后的 DOM，可以指明 `flush: 'post'`
          flush: 'post'
        }
      },
      methods: {
        increment() {
          this.count++
        },
        incrementObj() {
          this.countValObj.countVal.count++
        }
      }
    }).mount('#app')
  </script>


  <div id="app1">
    <button @click="increment">count: {{ count }}</button>
    <button @click="incrementXY">getter函数：{{ `${x} - ${y}` }}</button>
    <!-- <button @click="incrementObj">countValObj.countVal.count: {{ countValObj.countVal.count }}</button> -->
  </div>
  <script type="module">
    import { createApp, ref, watch, watchEffect } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
    createApp({
      setup() {
        const count = ref(0)
        function increment() {
          count.value++
        }

        // watch的第一个参数可以是
        //   1. ref
        //   2. 计算属性
        //   3. 一个响应式对象
        //   4. 一个getter函数
        //   5. 多个来源组成的数组
        watch(count, (newVal, oldVal) => {
          console.log('组合式 API, watch count: ', newVal, oldVal)
        })

        // 监听getter函数
        const x = ref(0)
        const y = ref(0)
        watch(() => x.value + y.value, (newVal, oldVal) => {
          console.log('监听 getter 函数, ', newVal, oldVal)
        }, {
          immediate: true
        })
        function incrementXY() {
          x.value++
          y.value++
        }

        // 多个来源组成的数组
        watch([x, () => y.value], ([newX, newY]) => {
          console.log(`x is ${newX} and y is ${newY}`)
        })

        // watchEffect
        watchEffect(() => {
          console.log(x.value, y.value)
        })

        return {
          count,
          increment,
          
          x,
          y,
          incrementXY
        }
      }
    }).mount('#app1')
  </script>


  <div id="app2">
    <p>
      Ask a yes/no question:
      <input v-model="question">
    </p>
    <p>{{ answer }}</p>
  </div>
  <script type="module">
    import { createApp, ref, watch } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
    createApp({
      setup() {
        const question = ref('')
        const answer = ref('Questions usually contain a question mark. ;-)');

        watch(question, async (newQuestion, oldQuestion) => {
          if(newQuestion.indexOf('?') > -1) {
            answer.value = 'Think...'
            try {
              const res = await fetch('https://yesno.wtf/api')
              answer.value = (await res.json()).answer
            } catch(error) {
              answer.value = 'Error! Could not reach the API. ' + error
            }
          }
        })

        return {
          question,
          answer
        }
      }
    }).mount('#app2')
  </script>
</body>
</html>